﻿#include "GUICreateSEACavitySelectPicklDialog.h"
#include "ui_GUICreateSEACavitySelectPicklDialog.h"

#include "FITK_Kernel/FITKCore/FITKActionOperator.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"

#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysCavity.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsGeometryData.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysShellPlate.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEAFace.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKSpectraDampingLossFactor.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsSpectraManager.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsPhysicsProp.h"
#include "FITK_Kernel/FITKCore/FITKDataRepo.h"
// Pick
#include "PickDataProvider/GUIPickInfo.h"
#include "PickDataProvider/PickedDataProvider.h"
#include "PickDataProvider/PickedData.h"

#include <QButtonGroup>
#include <QRegExpValidator>
#include <QTabBar>
#include <QMessageBox>

namespace GUI {

    GUICreateSEACavitySelectPicklDialog::GUICreateSEACavitySelectPicklDialog(Core::FITKActionOperator* oper, QWidget* parent /*= nullptr*/) :
        GUIDialogBase(parent),
        _oper(oper),
        _ui(new Ui::GUICreateSEACavitySelectPicklDialog)
    {
        _ui->setupUi(this);
        // 设置对话框关闭时自动删除
        setAttribute(Qt::WA_DeleteOnClose);
        //去掉问号
        Qt::WindowFlags flags = windowFlags();
        flags &= ~Qt::WindowContextHelpButtonHint;
        setWindowFlags(flags);
        //初始化界面
        this->init();
        //获取拾取器，绑定拾取结束信号
        GraphData::PickedDataProvider* pickProvider = GraphData::PickedDataProvider::getInstance();
        //清除拾取对象所有的连接
        QObject::disconnect(pickProvider, SIGNAL(sig_pickedOver()), nullptr, nullptr);
        if (pickProvider)
        {
            connect(pickProvider, &GraphData::PickedDataProvider::sig_pickedOver, this, &GUICreateSEACavitySelectPicklDialog::pickFinished);
            connect(pickProvider, &GraphData::PickedDataProvider::sig_pickedData, this, &GUICreateSEACavitySelectPicklDialog::pickDataFinished);
        }
        //设置窗口自适应隐藏组件
        this->layout()->setSizeConstraint(QLayout::SetMinAndMaxSize);
    }

    GUICreateSEACavitySelectPicklDialog::~GUICreateSEACavitySelectPicklDialog()
    {
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
    }

    Acoustics::FITKSEASubSysCavity * GUICreateSEACavitySelectPicklDialog::getCavityData()
    {
        return _cavityData;
    }

    void GUICreateSEACavitySelectPicklDialog::on_radioButton_Shell_clicked(bool checked)
    {
        if (!checked) return;
        _ui->label_Picked->setText(QString("Picked (0)"));
        //设置拾取方式
        GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
        pickInfo._pickObjType = GUI::GUIPickInfo::PickObjType::POBJSEAShell;
        pickInfo._pickMethod = GUI::GUIPickInfo::PickMethod::PMIndividually;
        GUI::GUIPickInfo::SetPickInfo(pickInfo);
    }

    void GUICreateSEACavitySelectPicklDialog::on_radioButton_Geometry_clicked(bool checked)
    {
        if (!checked) return;
        _ui->label_Picked->setText(QString("Picked (0)"));
        //设置拾取方式
        GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
        pickInfo._pickObjType = GUI::GUIPickInfo::PickObjType::POBJGeometrySolid;
        pickInfo._pickMethod = GUI::GUIPickInfo::PickMethod::PMSingle;
        GUI::GUIPickInfo::SetPickInfo(pickInfo);
    }

    void GUICreateSEACavitySelectPicklDialog::on_radioButton_Mesh_clicked(bool checked)
    {
        if (!checked) return;
        _ui->label_Picked->setText(QString("Picked (0)"));
        //设置拾取方式
        GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
        pickInfo._pickObjType = GUI::GUIPickInfo::PickObjType::POBJMeshCell3D;
        pickInfo._pickMethod = GUI::GUIPickInfo::PickMethod::PMIndividually;
        GUI::GUIPickInfo::SetPickInfo(pickInfo);
    }

    void GUICreateSEACavitySelectPicklDialog::on_pushButton_Cancel_clicked()
    {
        this->reject();
    }

    void GUICreateSEACavitySelectPicklDialog::on_pushButton_OK_clicked()
    {
        //获取子系统管理器
        Acoustics::FITKAcousticsSEASubSysManager* subSysMgr = _SEAModel->getSEASubSysManager();
        if (!_oper || !subSysMgr) return;
        //清理数据
        if (_cavityData)
            delete _cavityData;
        _cavityData = nullptr;
        //创建数据
        _cavityData = new Acoustics::FITKSEASubSysCavity;
        //通过几何创建声腔
        if (_ui->radioButton_Geometry->isChecked())
        {
            if (!this->createCavityByGeometry())
                return;
        }
        //通过板创建声腔
        else if (_ui->radioButton_Shell->isChecked())
        {
            if (!this->createCavityByShell())
                return;
        }
        //更新几何属性
        _cavityData->updateGeoProp();
        subSysMgr->appendDataObj(_cavityData);
        _oper->setArgs("DataID", _cavityData->getDataObjectID());
        this->accept();
    }

    bool GUICreateSEACavitySelectPicklDialog::createCavityByGeometry()
    {
        if (!_cavityData) return false;
        //获取几何数据和三维可视化对象管理
        Acoustics::FITKAcousticsGeometryData *comList = FITKGLODATA->getGeometryData<Acoustics::FITKAcousticsGeometryData>();
        GraphData::PickedDataProvider* pickProvider = GraphData::PickedDataProvider::getInstance();
        if (!pickProvider || !comList)return false;
        //获取拾取数据对象
        QList<GraphData::PickedData*> pickList = pickProvider->getPickedList();
        if (pickList.size() != 1)
        {
            QMessageBox::warning(this, "", tr("Create Cavity err! The number of GeometrySolid is 0."), QMessageBox::Ok);
            return false;
        }
        //获取几何实体数据
        GraphData::PickedData* pickDataP = pickList.at(0);
        if (pickDataP == nullptr)return false;
        int DataObjId = pickDataP->getPickedDataObjId();
        QList<int> pickedIds = pickDataP->getPickedIds();
        Interface::FITKAbsGeoCommand*comP = comList->getDataByID(DataObjId);
        if (!comP)
        {
            QMessageBox::warning(this, "", tr("Create Cavity err! Picked GeometrySolid data err."), QMessageBox::Ok);
            return false;
        }
        if (!_cavityData->genCavityByGeometry(comP, pickedIds.at(0)) || !_cavityData->isEnclosedSpace())
        {
            int count = _cavityData->getFaceCount();
            for (int i = 0; i < count; ++i)
            {
                Acoustics::FITKAbstractSEAFace* face =_cavityData->getFace(i);
                if (!face) continue;
                delete face;
            }
            QMessageBox::warning(this, "", tr("Create Cavity err! The picked up GeometrySolid do not form an enclosed space."), QMessageBox::Ok);
            return false;
        }
        if (!this->createSubShellByCavity())
        {
            int count = _cavityData->getFaceCount();
            for (int i = 0; i < count; ++i)
            {
                Acoustics::FITKAbstractSEAFace* face = _cavityData->getFace(i);
                if (!face) continue;
                delete face;
            }
            QMessageBox::warning(this, "", tr("Create Cavity err! Initializing the plate data corresponding to the acoustic cavity is incorrect."), QMessageBox::Ok);
            return false;
        }
        return true;
    }

    bool GUICreateSEACavitySelectPicklDialog::createCavityByShell()
    {
        if (!_cavityData) return false;
        //获取三维可视化对象管理
        GraphData::PickedDataProvider* pickProvider = GraphData::PickedDataProvider::getInstance();
        if (!pickProvider)return false;

        //获取拾取数据对象
        QList<GraphData::PickedData*> pickList = pickProvider->getPickedList();
        for (GraphData::PickedData* pickData : pickList)
        {
            if (!pickData) continue;
            int objID = pickData->getPickedDataObjId();
            _cavityData->appendShell(objID);
        }
        if (_cavityData->getShellCount() == 0)
        {
            QMessageBox::warning(this, "", tr("Create Cavity err! The number of plates is 0."), QMessageBox::Ok);
            return false;
        }
        if (!_cavityData->isEnclosedSpace())
        {
            QMessageBox::warning(this, "", tr("Create Cavity err! The picked up plates do not form an enclosed space."), QMessageBox::Ok);
            return false;
        }
        return true;
    }

    bool GUICreateSEACavitySelectPicklDialog::createSubShellByCavity()
    {
        if (!_cavityData || !_SEAModel || !_physics) return false;
        //获取子系统管理器
        Acoustics::FITKAcousticsSEASubSysManager* subSysMgr = _SEAModel->getSEASubSysManager();
        if (!subSysMgr) return false;
        //获取工况管理器
        Acoustics::FITKAcousticsSpectraManager* spectraMgr = _physics->getFITKAcousticsSpectraManager();
        Acoustics::FITKAcousticsPhysicsPropManager* phyMgr = _physics->getPhysicsPropManager();
        if (!spectraMgr || !phyMgr)return false;
        //获取数据
        QList<Acoustics::FITKAcousticsAbstractSpectra*> dampings = spectraMgr->getSpectraByType(Acoustics::FITKAcousticsAbstractSpectra::Damping);
        QList<Acoustics::FITKAcousticsAbsPhysicsProp*> uniformPlats = phyMgr->getPhysicsProps(Acoustics::FITKAcousticsAbsPhysicsProp::AcousticsPhyscisPropType::APPUniformPlat);
        if (dampings.isEmpty() || uniformPlats.isEmpty()) return false;
        //通过几何体创建声腔子系统后，该声腔使用的几何面转换为SEA板
        int faceCount = _cavityData->getFaceCount();
        //遍历创建该声腔的索引SEA面
        for (int i = 0; i < faceCount; ++i)
        {
            Acoustics::FITKAbstractSEAFace*FaceP = _cavityData->getFace(i);//面对象
            if (FaceP == nullptr)return false;
            int faceID = _cavityData->getFaceID(i);

            Acoustics::FITKSEASubSysPlateShell* flatPlate = new Acoustics::FITKSEASubSysPlateShell;
            flatPlate->setDataObjectName(subSysMgr->checkName("PlateShell-1"));
            flatPlate->setFaceID(faceID);
            //设置默认值
            flatPlate->setFlexureSpectraID(dampings.at(0)->getDataObjectID());
            flatPlate->setExtensionSpectraID(dampings.at(0)->getDataObjectID());
            flatPlate->setShearSpectraID(dampings.at(0)->getDataObjectID());
            flatPlate->setPropSection(uniformPlats.at(0)->getDataObjectID());

            subSysMgr->appendDataObj(flatPlate);//添加到管理器
            _cavityData->appendShell(flatPlate->getDataObjectID());
        }
        return true;
    }

    void GUICreateSEACavitySelectPicklDialog::reject()
    {
        //清除拾取模式和高亮
        GUI::GUIPickInfo::ClearPickInfo();
        this->QDialog::reject();
    }

    void GUICreateSEACavitySelectPicklDialog::init()
    {
        //获取子系统类型
        if (!_oper)return;
        _oper->argValue<int>("SEASubSysType", _subSysType);
        //初始化界面
        _ui->radioButton_Mesh->setVisible(false);
        _ui->radioButton_Shell->setChecked(true);
        this->on_radioButton_Shell_clicked(true);
    }

    void GUICreateSEACavitySelectPicklDialog::pickFinished()
    {
        this->on_pushButton_OK_clicked();
    }

    void GUICreateSEACavitySelectPicklDialog::pickDataFinished()
    {
        if (!_oper) return;
        //获取三维可视化对象管理
        GraphData::PickedDataProvider* pickProvider = GraphData::PickedDataProvider::getInstance();
        if (!pickProvider)return;
        QList<int> objIDList;

        //获取拾取数据对象
        QList<GraphData::PickedData*> pickList = pickProvider->getPickedList();
        for (GraphData::PickedData* pickData : pickList)
        {
            if (!pickData) continue;
            objIDList.append(pickData->getPickedDataObjId());
        }
        _ui->label_Picked->setText(QString("Picked (%1)").arg(objIDList.size()));
    }
}
